//
// Created by wxd on 2025/8/17.
//

#include "GridPlane.h"

#include "_018_plane_geometry_test.hpp"

void GridPlane::setGridWidth(float w) {
    m_GridWidth = w;
}

void GridPlane::setGridHeight(float h) {
    m_GridHeight = h;
}

void GridPlane::setGridSize(float wsize, float hsize) {
    m_GridWSize = wsize;
    m_GridHSize = hsize;
}


void GridPlane::setGridCenter(glm::vec3 center) {
    m_Center = center;
}

void GridPlane::setGridNormal(glm::vec3 normal) {
    m_Normal = normal;
}

void GridPlane::setGridAlternateColor(glm::vec3 colorA, glm::vec3 colorB) {
    m_ColorA = colorA;
    m_ColorB = colorB;
}

void GridPlane::setGridAlternateTexture(std::unique_ptr<Texture> textureA, std::unique_ptr<Texture> textureB) {
    m_PlaneTextureA = std::move(textureA);
    m_PlaneTextureB = std::move(textureB);
}

void GridPlane::setEnableAlternateGrid(bool enable) {
    m_EnableAlternateGrid = enable;
    m_EnableGridTexture = !enable;
}

void GridPlane::setEnableAlternateTexGrid(bool enable) {
    m_EnableGridTexture = enable;
    m_EnableAlternateGrid = !enable;
}

void GridPlane::setGridGenType(GridGenType type) {
    m_GridGenType = type;
}

int GridPlane::getGridType() const {
    return static_cast<int>(m_GridGenType);
}

void GridPlane::setShader(const std::string& vertexPath, const std::string& fragmentPath) {
    m_GridShader = std::make_unique<Shader>(vertexPath, fragmentPath);
}

void GridPlane::setGridAmbient(float ambient) {
    m_GridAmbient = glm::clamp(ambient, 0.f, 1.f);
}

Shader &GridPlane::getShader() const {
    return *m_GridShader;
}

Plane &GridPlane::getPlane() const {
    return *m_Plane;
}

glm::vec4 GridPlane::getGridScale() const {
    return {m_GridWidth, m_GridHeight, m_GridWSize, m_GridHSize};
}

glm::vec3 GridPlane::getGridCenter() const {
    return m_Center;
}

glm::vec3 GridPlane::getGridNormal() const {
    return m_Normal;
}

void GridPlane::setGridAmbientUniform() const {
    if (m_GridShader != nullptr) {
        m_GridShader->setUniform(uGridAmbient, m_GridAmbient);
    }
}

void GridPlane::setGridColorAUniform() const {
    if (m_GridShader != nullptr) {
        m_GridShader->setUniform(uGridColorA, m_ColorA);
    }
}

void GridPlane::setGridColorBUniform() const {
    if (m_GridShader != nullptr) {
        m_GridShader->setUniform(uGridColorB, m_ColorB);
    }
}

void GridPlane::setGridGenTypeUniform() const {
    if (m_GridShader != nullptr) {
        m_GridShader->setUniform(uGridGenType, getGridType());
    }
}

void GridPlane::setGridScaleUniform() const {
    if (m_GridShader != nullptr) {
        m_GridShader->setUniform(uGridScale, glm::vec4(m_GridWidth, m_GridHeight, m_GridWSize, m_GridHSize));
    }
}

void GridPlane::setGridMvpMatrix(const glm::mat4 &model, const glm::mat4 &view, const glm::mat4 &proj) const {
    m_GridShader->setUniform("uModel", model);
    m_GridShader->setUniform("uView", view);
    m_GridShader->setUniform("uProj", proj);
}

void GridPlane::draw(const glm::mat4& model, const glm::mat4& view, const glm::mat4& proj) {
    m_GridShader->bindProgram();
    setGridMvpMatrix(model, view, proj);
    setGridAmbientUniform();
    setGridGenTypeUniform();
    setGridColorAUniform();
    setGridColorBUniform();
    setGridScaleUniform();
    m_Plane->getVAO()->bind();
    m_Plane->draw();
    m_Plane->getVAO()->unbind();
    m_GridShader->unbindProgram();
}

void GridPlane::destroy() const {
    m_Plane->getEBO()->destroy();
    m_Plane->getVAO()->destroy();
    m_GridShader->deleteProgram();
}
